﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;

namespace BusinessLayer
{
    public class idvalidation
    {

        /// Represents a South African Identity Number.
        /// valid number = 7707215230080
        /// invalid test number = 1234567891234 

        [Serializable()]
        public class IdentityNumber
        {

            #region Enumerations
            public enum PersonGender
            {
                Female = 0,
                Male = 5
            }

            public enum PersonCitizenship
            {
                SouthAfrican = 0,
                Foreign = 1
            }
            #endregion

            #region Declarations
            static Regex _expression;
            Match _match;
            const string _IDExpression = @"(?<Year>[0-9][0-9])(?<Month>([0][1-9])|([1][0-2]))(?<Day>([0-2][0-9])|([3][0-1]))(?<Gender>[0-9])(?<Series>[0-9]{3})(?<Citizenship>[0-9])(?<Uniform>[0-9])(?<Control>[0-9])";
            #endregion

            #region Constuctors

            static IdentityNumber()
            {
                _expression = new Regex(_IDExpression, RegexOptions.Compiled | RegexOptions.Singleline);
            }


            public IdentityNumber(string IDNumber)
            {
                _match = _expression.Match(IDNumber.Trim());
            }
            #endregion

            #region Properties

            public DateTime DateOfBirth
            {
                get
                {
                    if (IsUsable == false)
                    {
                        throw new ArgumentException("ID Number is unusable!", "IDNumber");
                    }
                    int year = int.Parse(_match.Groups["Year"].Value);


                    int currentCentury = int.Parse(DateTime.Now.Year.ToString().Substring(0, 2) + "00");
                    int lastCentury = currentCentury - 100;
                    int currentYear = int.Parse(DateTime.Now.Year.ToString().Substring(2, 2));


                    if (year > currentYear)
                    {
                        year += lastCentury;
                    }
                    else
                    {
                        year += currentCentury;
                    }
                    return new DateTime(year, int.Parse(_match.Groups["Month"].Value), int.Parse(_match.Groups["Day"].Value));
                }
            }


            public PersonGender Gender
            {
                get
                {
                    if (IsUsable == false)
                    {
                        throw new ArgumentException("ID Number is unusable!", "IDNumber");
                    }
                    int gender = int.Parse(_match.Groups["Gender"].Value);
                    if (gender < (int)PersonGender.Male)
                    {
                        return PersonGender.Female;
                    }
                    else
                    {
                        return PersonGender.Male;
                    }
                }
            }


            public PersonCitizenship Citizenship
            {
                get
                {
                    if (IsUsable == false)
                    {
                        throw new ArgumentException("ID Number is unusable!", "IDNumber");
                    }
                    return (PersonCitizenship)Enum.Parse(typeof(PersonCitizenship), _match.Groups["Citizenship"].Value);
                }
            }


            public bool IsUsable
            {
                get
                {
                    return _match.Success;
                }
            }



            public bool IsValid
            {
                get
                {
                    if (IsUsable == true)
                    {


                        int a = int.Parse(_match.Value.Substring(0, 1)) + int.Parse(_match.Value.Substring(2, 1)) + int.Parse(_match.Value.Substring(4, 1)) + int.Parse(_match.Value.Substring(6, 1)) + int.Parse(_match.Value.Substring(8, 1)) + int.Parse(_match.Value.Substring(10, 1));


                        int b = int.Parse(_match.Value.Substring(1, 1) + _match.Value.Substring(3, 1) + _match.Value.Substring(5, 1) + _match.Value.Substring(7, 1) + _match.Value.Substring(9, 1) + _match.Value.Substring(11, 1));
                        b *= 2;
                        string bString = b.ToString();
                        b = 0;
                        for (int index = 0; index < bString.Length; index++)
                        {
                            b += int.Parse(bString.Substring(index, 1));
                        }


                        int c = a + b;


                        string cString = c.ToString();
                        cString = cString.Substring(cString.Length - 1, 1);
                        int control = 0;


                        if (cString != "0")
                        {
                            control = 10 - int.Parse(cString.Substring(cString.Length - 1, 1));
                        }

                        if (_match.Groups["Control"].Value == control.ToString())
                        {
                            return true;
                        }
                    }

                    return false;
                }
            }
            #endregion

        }
    }
}